/*!
    \file    dmx512_test.c
    \brief   DMX512灯带测试函数实现文件

    \version 2025-01-20, V1.0.0, DMX512测试函数 for GD32C231C
*/

#include "dmx512_test.h"
#include "systick.h"
#include <string.h>
#include <stdlib.h>
#include <math.h>

/* 全局测试配置 */
dmx512_test_config_t g_dmx512_test;

/* 效果名称数组 */
static const char* effect_names[DMX512_EFFECT_COUNT] = {
    "Solid Red",
    "Solid Green",
    "Solid Blue",
    "Solid White",
    "Rainbow",
    "Breathing",
    "Flowing",
    "Gradient",
    "Twinkle",
    "Wave",
    "Fire",
    "Police"
};

/* 简化的正弦表 (0-90度，256个值) */
static const uint8_t sin_table[91] = {
    0, 4, 9, 13, 18, 22, 27, 31, 35, 40, 44, 48, 53, 57, 61, 65,
    70, 74, 78, 82, 86, 90, 94, 98, 102, 106, 109, 113, 117, 121, 125, 128,
    132, 136, 139, 143, 146, 150, 153, 156, 160, 163, 166, 169, 172, 175, 178, 181,
    184, 187, 190, 192, 195, 198, 200, 203, 205, 208, 210, 212, 215, 217, 219, 221,
    223, 225, 227, 229, 231, 233, 234, 236, 238, 239, 241, 242, 244, 245, 246, 248,
    249, 250, 251, 252, 253, 254, 254, 255, 255, 255, 255
};

/*!
    \brief      初始化DMX512测试
    \param[in]  led_count: LED数量
    \param[in]  auto_cycle: 是否自动循环效果
    \param[out] none
    \retval     none
*/
void dmx512_test_init(uint16_t led_count, bool auto_cycle)
{
    memset(&g_dmx512_test, 0, sizeof(dmx512_test_config_t));
    
    g_dmx512_test.led_count = led_count;
    g_dmx512_test.effect_duration_ms = 5000; /* 每个效果持续5秒 */
    g_dmx512_test.update_interval_ms = 50;   /* 20Hz更新频率 */
    g_dmx512_test.auto_cycle = auto_cycle;
    g_dmx512_test.current_effect = DMX512_EFFECT_SOLID_RED;
    g_dmx512_test.effect_step = 0;
    g_dmx512_test.effect_timer = 0;
}

/*!
    \brief      运行DMX512测试
    \param[in]  none
    \param[out] none
    \retval     none
*/
void dmx512_test_run(void)
{
    /* 更新效果计时器 */
    g_dmx512_test.effect_timer += g_dmx512_test.update_interval_ms;
    
    /* 检查是否需要切换效果 */
    if (g_dmx512_test.auto_cycle && 
        g_dmx512_test.effect_timer >= g_dmx512_test.effect_duration_ms) {
        dmx512_test_next_effect();
        g_dmx512_test.effect_timer = 0;
        g_dmx512_test.effect_step = 0;
    }
    
    /* 执行当前效果 */
    switch (g_dmx512_test.current_effect) {
        case DMX512_EFFECT_SOLID_RED:
            dmx512_test_solid_color_effect(DMX512_COLOR_RED, g_dmx512_test.led_count);
            break;
            
        case DMX512_EFFECT_SOLID_GREEN:
            dmx512_test_solid_color_effect(DMX512_COLOR_GREEN, g_dmx512_test.led_count);
            break;
            
        case DMX512_EFFECT_SOLID_BLUE:
            dmx512_test_solid_color_effect(DMX512_COLOR_BLUE, g_dmx512_test.led_count);
            break;
            
        case DMX512_EFFECT_SOLID_WHITE:
            dmx512_test_solid_color_effect(DMX512_COLOR_WHITE, g_dmx512_test.led_count);
            break;
            
        case DMX512_EFFECT_RAINBOW:
            dmx512_test_rainbow_effect(g_dmx512_test.led_count, g_dmx512_test.effect_step);
            break;
            
        case DMX512_EFFECT_BREATHING:
            dmx512_test_breathing_effect(DMX512_COLOR_WHITE, g_dmx512_test.led_count, g_dmx512_test.effect_step);
            break;
            
        case DMX512_EFFECT_FLOWING:
            dmx512_test_flowing_effect(DMX512_COLOR_CYAN, g_dmx512_test.led_count, g_dmx512_test.effect_step);
            break;
            
        case DMX512_EFFECT_GRADIENT:
            dmx512_test_gradient_effect(DMX512_COLOR_ORANGE, DMX512_COLOR_PURPLE, g_dmx512_test.led_count, g_dmx512_test.effect_step);
            break;
            
        case DMX512_EFFECT_TWINKLE:
            dmx512_test_twinkle_effect(DMX512_COLOR_WHITE, g_dmx512_test.led_count, g_dmx512_test.effect_step);
            break;
            
        case DMX512_EFFECT_WAVE:
            dmx512_test_wave_effect(DMX512_COLOR_PURPLE, g_dmx512_test.led_count, g_dmx512_test.effect_step);
            break;
            
        case DMX512_EFFECT_FIRE:
            dmx512_test_fire_effect(g_dmx512_test.led_count, g_dmx512_test.effect_step);
            break;
            
        case DMX512_EFFECT_POLICE:
            dmx512_test_police_effect(g_dmx512_test.led_count, g_dmx512_test.effect_step);
            break;
            
        default:
            g_dmx512_test.current_effect = DMX512_EFFECT_SOLID_RED;
            break;
    }
    
    /* 增加效果步骤 */
    g_dmx512_test.effect_step++;
}

/*!
    \brief      设置当前测试效果
    \param[in]  effect: 效果类型
    \param[out] none
    \retval     none
*/
void dmx512_test_set_effect(dmx512_effect_t effect)
{
    if (effect < DMX512_EFFECT_COUNT) {
        g_dmx512_test.current_effect = effect;
        g_dmx512_test.effect_step = 0;
        g_dmx512_test.effect_timer = 0;
    }
}

/*!
    \brief      获取当前测试效果
    \param[in]  none
    \param[out] none
    \retval     当前效果类型
*/
dmx512_effect_t dmx512_test_get_effect(void)
{
    return g_dmx512_test.current_effect;
}

/*!
    \brief      切换到下一个效果
    \param[in]  none
    \param[out] none
    \retval     none
*/
void dmx512_test_next_effect(void)
{
    g_dmx512_test.current_effect++;
    if (g_dmx512_test.current_effect >= DMX512_EFFECT_COUNT) {
        g_dmx512_test.current_effect = DMX512_EFFECT_SOLID_RED;
    }
    g_dmx512_test.effect_step = 0;
    g_dmx512_test.effect_timer = 0;
}

/*!
    \brief      获取效果名称
    \param[in]  effect: 效果类型
    \param[out] none
    \retval     效果名称字符串
*/
const char* dmx512_test_get_effect_name(dmx512_effect_t effect)
{
    if (effect < DMX512_EFFECT_COUNT) {
        return effect_names[effect];
    }
    return "未知效果";
}

/*!
    \brief      纯色效果
    \param[in]  color: RGB颜色
    \param[in]  led_count: LED数量
    \param[out] none
    \retval     none
*/
void dmx512_test_solid_color_effect(rgb_color_t color, uint16_t led_count)
{
    dmx512_set_all_color(color, led_count);
}

/*!
    \brief      彩虹效果
    \param[in]  led_count: LED数量
    \param[in]  step: 动画步骤
    \param[out] none
    \retval     none
*/
void dmx512_test_rainbow_effect(uint16_t led_count, uint32_t step)
{
    uint16_t i;
    uint16_t channel = 1;
    uint16_t hue;
    rgb_color_t color;
    
    for (i = 0; i < led_count && channel <= (g_dmx512.channel_count - 2); i++) {
        hue = (i * 360 / led_count + step * 2) % 360;
        color = dmx512_hsv_to_rgb(hue, 255, 255);
        dmx512_set_rgb(channel, color);
        channel += 3;
    }
}

/*!
    \brief      呼吸灯效果
    \param[in]  color: 基础颜色
    \param[in]  led_count: LED数量
    \param[in]  step: 动画步骤
    \param[out] none
    \retval     none
*/
void dmx512_test_breathing_effect(rgb_color_t color, uint16_t led_count, uint32_t step)
{
    uint8_t brightness = dmx512_test_sin((step * 4) % 360);
    rgb_color_t adjusted_color = dmx512_adjust_brightness(color, brightness);
    dmx512_set_all_color(adjusted_color, led_count);
}

/*!
    \brief      流水灯效果
    \param[in]  color: 流水灯颜色
    \param[in]  led_count: LED数量
    \param[in]  step: 动画步骤
    \param[out] none
    \retval     none
*/
void dmx512_test_flowing_effect(rgb_color_t color, uint16_t led_count, uint32_t step)
{
    uint16_t position = step % led_count;
    dmx512_flowing_effect(color, led_count, position, 5);
}

/*!
    \brief      渐变效果
    \param[in]  start_color: 起始颜色
    \param[in]  end_color: 结束颜色
    \param[in]  led_count: LED数量
    \param[in]  step: 动画步骤
    \param[out] none
    \retval     none
*/
void dmx512_test_gradient_effect(rgb_color_t start_color, rgb_color_t end_color, uint16_t led_count, uint32_t step)
{
    uint16_t i;
    uint16_t channel = 1;
    rgb_color_t blend_color;
    uint8_t ratio;
    uint8_t wave_offset = dmx512_test_sin((step * 2) % 360);
    
    for (i = 0; i < led_count && channel <= (g_dmx512.channel_count - 2); i++) {
        ratio = (i * 255) / (led_count - 1);
        ratio = (ratio + wave_offset) % 256;
        blend_color = dmx512_test_blend_colors(start_color, end_color, ratio);
        dmx512_set_rgb(channel, blend_color);
        channel += 3;
    }
}

/*!
    \brief      闪烁效果
    \param[in]  color: 闪烁颜色
    \param[in]  led_count: LED数量
    \param[in]  step: 动画步骤
    \param[out] none
    \retval     none
*/
void dmx512_test_twinkle_effect(rgb_color_t color, uint16_t led_count, uint32_t step)
{
    uint16_t i;
    uint16_t channel = 1;
    rgb_color_t led_color;
    uint8_t brightness;
    
    /* 清除所有LED */
    dmx512_set_all_color(DMX512_COLOR_BLACK, led_count);
    
    /* 随机闪烁一些LED */
    for (i = 0; i < led_count && channel <= (g_dmx512.channel_count - 2); i++) {
        if ((step + i * 7) % 20 < 3) { /* 约15%的LED闪烁 */
            brightness = 128 + dmx512_test_sin((step * 10 + i * 30) % 360) / 2;
            led_color = dmx512_adjust_brightness(color, brightness);
            dmx512_set_rgb(channel, led_color);
        }
        channel += 3;
    }
}

/*!
    \brief      波浪效果
    \param[in]  color: 波浪颜色
    \param[in]  led_count: LED数量
    \param[in]  step: 动画步骤
    \param[out] none
    \retval     none
*/
void dmx512_test_wave_effect(rgb_color_t color, uint16_t led_count, uint32_t step)
{
    uint16_t i;
    uint16_t channel = 1;
    rgb_color_t led_color;
    uint8_t brightness;
    uint16_t wave_angle;
    
    for (i = 0; i < led_count && channel <= (g_dmx512.channel_count - 2); i++) {
        wave_angle = (step * 5 + i * 360 / led_count) % 360;
        brightness = 128 + dmx512_test_sin(wave_angle) / 2;
        led_color = dmx512_adjust_brightness(color, brightness);
        dmx512_set_rgb(channel, led_color);
        channel += 3;
    }
}

/*!
    \brief      火焰效果
    \param[in]  led_count: LED数量
    \param[in]  step: 动画步骤
    \param[out] none
    \retval     none
*/
void dmx512_test_fire_effect(uint16_t led_count, uint32_t step)
{
    uint16_t i;
    uint16_t channel = 1;
    rgb_color_t fire_color;
    uint8_t red, green, blue;
    
    for (i = 0; i < led_count && channel <= (g_dmx512.channel_count - 2); i++) {
        /* 生成火焰颜色：红色为主，橙色和黄色变化 */
        red = 200 + (rand() % 56); /* 200-255 */
        green = (rand() % 100);     /* 0-99 */
        blue = 0;
        
        /* 底部更亮，顶部更暗 */
        if (i < led_count / 2) {
            green += (led_count / 2 - i) * 50 / (led_count / 2);
            if (green > 255) green = 255;
        }
        
        fire_color.red = red;
        fire_color.green = green;
        fire_color.blue = blue;
        
        dmx512_set_rgb(channel, fire_color);
        channel += 3;
    }
}

/*!
    \brief      警灯效果
    \param[in]  led_count: LED数量
    \param[in]  step: 动画步骤
    \param[out] none
    \retval     none
*/
void dmx512_test_police_effect(uint16_t led_count, uint32_t step)
{
    uint16_t i;
    uint16_t channel = 1;
    rgb_color_t led_color;
    uint16_t half_count = led_count / 2;
    
    /* 清除所有LED */
    dmx512_set_all_color(DMX512_COLOR_BLACK, led_count);
    
    if ((step / 10) % 2 == 0) {
        /* 红色闪烁 - 左半部分 */
        for (i = 0; i < half_count && channel <= (g_dmx512.channel_count - 2); i++) {
            led_color = DMX512_COLOR_RED;
            dmx512_set_rgb(channel, led_color);
            channel += 3;
        }
    } else {
        /* 蓝色闪烁 - 右半部分 */
        channel = 1 + half_count * 3;
        for (i = half_count; i < led_count && channel <= (g_dmx512.channel_count - 2); i++) {
            led_color = DMX512_COLOR_BLUE;
            dmx512_set_rgb(channel, led_color);
            channel += 3;
        }
    }
}

/*!
    \brief      生成随机颜色
    \param[in]  none
    \param[out] none
    \retval     随机RGB颜色
*/
rgb_color_t dmx512_test_random_color(void)
{
    rgb_color_t color;
    color.red = rand() % 256;
    color.green = rand() % 256;
    color.blue = rand() % 256;
    return color;
}

/*!
    \brief      颜色混合
    \param[in]  color1: 颜色1
    \param[in]  color2: 颜色2
    \param[in]  ratio: 混合比例 (0-255)
    \param[out] none
    \retval     混合后的颜色
*/
rgb_color_t dmx512_test_blend_colors(rgb_color_t color1, rgb_color_t color2, uint8_t ratio)
{
    rgb_color_t result;
    uint16_t inv_ratio = 255 - ratio;
    
    result.red = (color1.red * inv_ratio + color2.red * ratio) >> 8;
    result.green = (color1.green * inv_ratio + color2.green * ratio) >> 8;
    result.blue = (color1.blue * inv_ratio + color2.blue * ratio) >> 8;
    
    return result;
}

/*!
    \brief      正弦波计算
    \param[in]  angle: 角度 (0-359)
    \param[out] none
    \retval     正弦值 (0-255)
*/
uint8_t dmx512_test_sin(uint16_t angle)
{
    angle = angle % 360;
    
    if (angle <= 90) {
        return sin_table[angle];
    } else if (angle <= 180) {
        return sin_table[180 - angle];
    } else if (angle <= 270) {
        return sin_table[angle - 180];
    } else {
        return sin_table[360 - angle];
    }
}

/*!
    \brief      余弦波计算
    \param[in]  angle: 角度 (0-359)
    \param[out] none
    \retval     余弦值 (0-255)
*/
uint8_t dmx512_test_cos(uint16_t angle)
{
    return dmx512_test_sin((angle + 90) % 360);
}